﻿using OF.Lib.DataAccess.Core;
using OF.Lib.DataAccess.Entity;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace OF.Lib.DataAccess
{
    /// <summary>
    /// 分布式数据事务管理器DDTM：DDTM ddtm=new DDTM();
    /// </summary>
    public class DDTM : IDbTransaction
    {

        /// <summary>
        /// DB连接事务资源池，key为连接字符串，tuple-item1为IDbConnection（连接对象），tuple-item为IDbTransaction（事务对象）
        /// </summary>
        private Dictionary<string, Tuple<IDbConnection, IDbTransaction>> m_ConnectionPool = new Dictionary<string, Tuple<IDbConnection, IDbTransaction>>();

        public DDTM()
        {

        }

        /// <summary>
        /// 获取基于配置文件中Sql脚本的DBConnection
        /// </summary>
        /// <param name="sqlKey"></param>
        /// <param name="sqlStr"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public Tuple<IDbConnection, IDbTransaction> GetDbConnectionAndTransaction(string sqlKey, out string sqlStr, out int timeOut)
        {
            SQL sqlConfig = SQLConfigHelper.GetSQL(sqlKey);
            DBGroup groupConfig = DBConfigHelper.GetDBGroup(sqlConfig.ConnKey);

            //预留工厂方法，可以取不同的Slave服务器群的负载实现方式
            IDbConnConfig dbConnConfigFactory = new DbConnConfigRandomImpl();
            DBConn dbConnConfig = dbConnConfigFactory.GetDbConnConfig(sqlConfig, groupConfig);

            timeOut = 60;
            sqlStr = sqlConfig.Text;
            if (sqlConfig.TimeOut > 0)
            {
                timeOut = sqlConfig.TimeOut;
            }
            else
            {
                if (dbConnConfig.TimeOut > 0)
                {
                    timeOut = dbConnConfig.TimeOut;
                }
            }
            if (m_ConnectionPool.Keys.Contains(dbConnConfig.ConnStr.Trim().ToUpper()))
            { 
                return m_ConnectionPool[dbConnConfig.ConnStr];
            }
            else
            {
                IDbConnection dbConn = DbConnFactory.GetDbConnection(groupConfig.DBType, dbConnConfig.ConnStr);
                bool wasClosed = dbConn.State == ConnectionState.Closed;
                if (wasClosed)
                {
                    dbConn.Open();
                }
                IDbTransaction transaction = dbConn.BeginTransaction();
                Tuple<IDbConnection, IDbTransaction> tuple = new Tuple<IDbConnection, IDbTransaction>(dbConn, transaction);
                m_ConnectionPool.Add(dbConnConfig.ConnStr.Trim().ToUpper(), tuple);
                return tuple;
            }
        }

        /// <summary>
        /// 获取基于单个对象自动生成的DBConnection
        /// </summary>
        /// <param name="connKey"></param>
        /// <param name="isMasterDB"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public Tuple<IDbConnection, IDbTransaction> GetDbConnectionAndTransaction(string connKey, bool isMasterDB, out int timeOut )
        {
            DBGroup groupConfig = DBConfigHelper.GetDBGroup(connKey);
            //预留工厂方法，可以取不同的Slave服务器群的负载实现方式
            IDbConnConfig dbConnConfigFactory = new DbConnConfigRandomImpl();
            DBConn dbConnConfig = dbConnConfigFactory.GetDbConnConfig(isMasterDB, groupConfig);

            timeOut = 60;
            if (dbConnConfig.TimeOut > 0)
            {
                timeOut = dbConnConfig.TimeOut;
            }

            if (m_ConnectionPool.Keys.Contains(dbConnConfig.ConnStr.Trim().ToUpper()))
            { 
                return m_ConnectionPool[dbConnConfig.ConnStr.Trim().ToUpper()];
            }
            else
            {

                IDbConnection dbConn = DbConnFactory.GetDbConnection(groupConfig.DBType, dbConnConfig.ConnStr);
                bool wasClosed = dbConn.State == ConnectionState.Closed;
                if (wasClosed)
                {
                    dbConn.Open();
                }
                IDbTransaction transaction = dbConn.BeginTransaction();
                Tuple<IDbConnection, IDbTransaction> tuple = new Tuple<IDbConnection, IDbTransaction>(dbConn, transaction);
                m_ConnectionPool.Add(dbConnConfig.ConnStr.Trim().ToUpper(), tuple);
                return tuple;
            }        
        }
        
        /// <summary>
        /// 禁用此属性
        /// </summary>
        public IDbConnection Connection => throw new NotImplementedException();

        /// <summary>
        /// 禁用此属性
        /// </summary>
        public IsolationLevel IsolationLevel => throw new NotImplementedException();

        public void Commit()
        {
            foreach(var item in m_ConnectionPool.Values)
            {
                item.Item2.Commit();
            }
        }

        public void Dispose()
        {
            foreach (var item in m_ConnectionPool.Values)
            {
               if(item.Item1.State != ConnectionState.Closed)
                {
                    item.Item1.Close();
                }
            }

            m_ConnectionPool.Clear();
        }

        public void Rollback()
        {
            foreach (var item in m_ConnectionPool.Values)
            {
                item.Item2.Rollback();
            }
        }
    }


}
